using System;
using System.Collections.Generic;
using Me.Prettyprint.Cassandra.Serializers;
using Me.Prettyprint.Cassandra.Service.Template;
using Me.Prettyprint.Cassandra.Utils;
using Me.Prettyprint.Hector.Api;
using Me.Prettyprint.Hector.Api.Beans;
using Me.Prettyprint.Hector.Api.Exceptions;
using Me.Prettyprint.Hector.Api.Factory;
using Me.Prettyprint.Hector.Api.Mutation;
using Me.Prettyprint.Hector.Api.Query;

namespace Me.Prettyprint.Cassandra.Service
{
    /// <summary>
    /// IEnumerator for iterating over column slice.
    /// </summary>
    /// <typeparam name="K"></typeparam>
    /// <typeparam name="N"></typeparam>
    /// <typeparam name="V"></typeparam>
	public class ColumnSliceEnumerator<K, N, V> : IEnumerator<HColumn<N, V>>
	{
        private const int DEFAULT_COUNT = 100;
        private SliceQuery<K, N, V> query;
        private QueryResult<ColumnSlice<N, V>> result;
        private IEnumerator<HColumn<N, V>> enumerator;
        private N start;
        private ColumnSliceFinish<N> finish;
        private SliceFilter<HColumn<N, V>> filter = null;
        private bool reversed;
        private int count = DEFAULT_COUNT;
        private int columns = 0;

        public ColumnSliceEnumerator(SliceQuery<K, N, V> query, N start, N finish, bool reversed) :
            this(query, start, finish, reversed, DEFAULT_COUNT)
        {
        }
        public ColumnSliceEnumerator(SliceQuery<K, N, V> query, N start, N finish, bool reversed, int count) :
            this(query, start, new ColumnSliceFinish<N>(finish), reversed, count)
        {
        }
        public ColumnSliceEnumerator(SliceQuery<K, N, V> query, N start, ColumnSliceFinish<N> finish, bool reversed) :
            this(query, start, finish, reversed, DEFAULT_COUNT)
        {
        }
        public ColumnSliceEnumerator(SliceQuery<K, N, V> query, N start, ColumnSliceFinish<N> finish, bool reversed, int count)
        {
            this.query = query;
            this.start = start;
            this.finish = finish;
            this.reversed = reversed;
            this.count = count;
            this.query.SetRange(this.start, this.finish.Function(), this.reversed, this.count);
            this.result = this.query.Execute();
        }
        public ColumnSliceEnumerator<K, N, V> setFilter(SliceFilter<HColumn<N, V>> filter)
        {
            this.filter = filter;
            return this;
        }
        public bool MoveNext()
        {
            if (enumerator == null)
            {
                enumerator = this.result.Get().GetColumns().GetEnumerator();
            }
            bool next = enumerator.MoveNext();
            return next;
        }
        public HColumn<N, V> Current
        {
            get
            {
                return enumerator.Current;
            }
        }
        object System.Collections.IEnumerator.Current
        {
            get { return this.Current; }
        }
        public void Reset()
        {
            enumerator = null;
        }
        public void Dispose()
        {
            query = null;
            result = null;
            start = default(N);
            finish = null;
            enumerator = null;
        }
    }
    public class ColumnSliceFinish<N>
    {
        public ColumnSliceFinish(N finish)
        {
            Finish = finish;
        }
        protected N Finish
        {
            get;
            set;
        }
        public N Function()
        {
            return Finish;
        }
    }
}